package finalapp.exercise.db;

import finalapp.exercise.db.LocationsDB.Places;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

/**
 * Clase que utilizaremos para que la informacion de nuestra aplicacion
 * sea accesible al resto de aplicaciones Android
 * 
 * @author Alejandro Villamarin
 *
 */
public class LocationsProvider extends ContentProvider {
	
	/** 
	 * Nombre del provider
	 */
    public static final String PROVIDER_NAME = "finalapp.exercise.db.locationsprovider";
    
    /**
     * Uri del provider
     */
    public static final Uri CONTENT_URI = Uri.parse("content://"+ PROVIDER_NAME);
	public static final int LOCATION = 1;
	public static final int LOCATION_ID = 2;
	
	private static final UriMatcher uriMatcher;
	static {
		uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		uriMatcher.addURI(PROVIDER_NAME, "location", LOCATION);
		uriMatcher.addURI(PROVIDER_NAME, "location/#", LOCATION_ID);
	}
	
	/**
	 * La base de datos
	 */
	private SQLiteDatabase locationsDB;

	/**
	 * Llamado cuando se crea el Provider, crea la base de datos
	 * llamando al helper
	 * 
	 * @return	TRUE si la base de datos se ha creado correctamente
	 */
	@Override
	public boolean onCreate() {
		LocationsSQLHelper locationsDbHelper = new LocationsSQLHelper(getContext());
		locationsDB = locationsDbHelper.getWritableDatabase();
		return (locationsDB == null) ? false : true;
	}
	
	/**
	 * Devuelve el MIME type para el dato especificado en la Uri
	 * @param	uri	La uri con el tipo de dato
	 * @return	String con el tipo MIME para la uri indicada
	 */
	@Override
	public String getType(Uri uri) {
		switch(uriMatcher.match(uri)) {
			case LOCATION: // Para un conjunto de locations
				return("vnd.android.cursor.dir/vnd.finalapp.location");
			case LOCATION_ID: //Para un location especifico
				return("vnd.android.cursor.item/vnd.finalapp.location");
			default:
				throw new IllegalArgumentException ("Unsupported URI:" + uri);
		}
	}
	/**
	 * Metodo que se llama cuando se elimina una localizacion o todas
	 * @param	uri			La uri del elemento a eliminar
	 * @param	where		Clausula where de la sentencia
	 * @param	whereargs	Argumentos para el where si se quieren usar parametros tipo %d, %s, etc
	 * @return	El numero de registros eliminados
	 */
	@Override
	public int delete(Uri uri, String where, String[] whereargs) {
		
		int count = 0;
		
		switch(uriMatcher.match(uri)) {
			//si hay que eliminar todas
			case LOCATION:
				//cuantos registros eliminamos?
				count = locationsDB.delete(Places.TABLE_NAME, where, whereargs);
				break;
			case LOCATION_ID:
				//obtenemos el id del uri
				String id = uri.getPathSegments().get(1);
				//construimos la clausula where
				String whereId = Places._ID + " = " + id + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : "");
				//eliminamos el registro
				count = locationsDB.delete(Places.TABLE_NAME, whereId, whereargs);
				break;
			default:
				throw new IllegalArgumentException("Unknown URI" + uri);
		}
		//notificamos a los observers que se ha eliminado un registro o varios
		getContext().getContentResolver().notifyChange(uri, null);
		return(count);
	}
	
	/**
	 * Metodo que introduce un nuevo registro en la base de datos
	 * @param	uri		Uri del provider
	 * @param	values	Valores para la sentencia INSERT
	 * @return	Una uri que representa el elemento añadido
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		
		//introducimos el registro y obtenemos el id
		long rowID = locationsDB.insert(Places.TABLE_NAME, "", values);

		// Si todo ha ido OK devolveremos su URI
		if (rowID > 0) {
			Uri baseUri = Uri.parse("content://" + PROVIDER_NAME + "/location");
			Uri _uri = ContentUris.withAppendedId(baseUri, rowID);
			getContext().getContentResolver().notifyChange(_uri, null);
			getContext().getContentResolver().notifyChange(baseUri, null);
			return(_uri);
		}
		throw new SQLException("Failed to insert row into" + uri);
	}

	/**
	 * Metodo que realiza una query sobre la base de datos
	 * @param	uri				Uri del provider
	 * @param	projection		Proyeccion sobre los datos que queremos obtener, es como una vista
	 * @param	selection		Clausula where de la sentencia
	 * @param	selectionArgs	Argumentos para la clausula where en el caso de que se quieran usar
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
		
		//constructor de la query
		SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
		//especificamos la tabla
		builder.setTables(Places.TABLE_NAME);
		
		if(uriMatcher.match(uri) == LOCATION_ID) {
			//obtenemos el id
			String id = uri.getPathSegments().get(1);
			//incluimos el id a la clausula where
			builder.appendWhere(Places._ID + " = " + id);
		}
		//si no hay orden establecido obtenemos el por defecto
		if(sortOrder == null || sortOrder == "") {
			sortOrder = Places.DEFAULT_SORT_ORDER;
		}
		
		//lanzamos la query obteniendo un cursor
		Cursor c = builder.query(locationsDB, projection, selection, selectionArgs, null, null, sortOrder);
		// Registramos los cambios para que se enteren nuestros observadores
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return(c);
	}

	/**
	 * Metodo que realiza modifica un registro ya existente en la base de datos
	 * @param	uri 			La uri del provider
	 * @param	values			Los valores para hacer la sentencia update
	 * @param	selection		Clausula where
	 * @param	selectionArgs	Argumentos para la clausula where (opcionales)
	 * @return	El numero de registros modificados
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
		//contador de filas actualizadas
		int count = 0;
		
		switch(uriMatcher.match(uri)) {
			//todas las localizaciones
			case LOCATION:
				count = locationsDB.update(Places.TABLE_NAME, values, selection, selectionArgs);
				break;
			//una localizacion especifica
			case LOCATION_ID:
				//obtenemos el id
				String id = uri.getPathSegments().get(1);
				//contruimos la clausula where del update
				String selectionId = Places._ID + " = " + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
				count = locationsDB.update(Places.TABLE_NAME, values, selectionId, selectionArgs);
				break;
			default:
				throw new IllegalArgumentException("Unknown URI:" + uri);
		}
		//notificamos a los observers que se han actulizado localizaciones
		getContext().getContentResolver().notifyChange(uri, null);
		return(count);
	}
}
